package com.etu.upload;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * 文件上传的实现类。
 * 通过此类可以实现文件上传。
 *@author xinyu126
 *@date Jan 17, 2010
 */
public class UploadByFile extends UploadBase  {
	
	private UploadControlable control;
	private String fileName;
	private String path;
	private String fileType;
	private long fileSize=5120000;
	
	/**
	 * 使用默认的控制器实现上传的构造方法
	 * 默认的控制器是文件大小5MB 文件类型不限，默认位置是tomcat的根目录
	 * 默认的缓冲区大小
	 * @param req 一个包含<code>request</code>的简单封装类
	 * @throws IOException
	 */
	public UploadByFile(RequestContextImpl req) throws IOException {
		this(req,null,UploadBase.DEFAULT_BUFSIZE);
	}
	
	public UploadByFile(RequestContextImpl req, UploadControlable control) throws IOException {
		this(req,control,UploadBase.DEFAULT_BUFSIZE);
	}
	
	public UploadByFile(RequestContextImpl req, UploadControlable control,
			int bufSize) throws IOException {
		super(req, bufSize);
		if(control!=null){
			this.control=control;
		}else{
			control=new Control();
		}
        fileName=header.getFileName();
        path=header.getValue("folder");
        fileType=header.getFileType();
	}
	
	 /**
     * 这个是主要的方法上传的核心方法。所有的判断，设置应该在这个方法之前调用
     * @return <code>true</code>if upload succeed
     * */
    public boolean upload() throws IOException{    	
      
    	if(checkType(fileType)){
    		return false;
    	}
    	boolean flag=false;
    	FileChannel out=null;
    	File file=createFile(path,fileName);
    	try {    		
        	FileOutputStream fout = new FileOutputStream( file );
        	out = fout.getChannel();  
            String strSize=header.getValue("fileSize");
          
            if(strSize!=null){
            	long size=Long.parseLong(strSize);
            	flag=output(out,size);
            }
            else{
            	flag=output(out);
            }	
		} catch (IOException e) {			
			e.printStackTrace();
		}finally{
			out.close();
			
			if(!flag)file.delete();
		}
		return flag;
    }
    

    private boolean output(FileChannel out) throws IOException{     	
		ByteBuffer buffer2=ByteBuffer.allocate(bufSize);
		boolean flag=true;
		//
		while(true){
			int n,m=0;
			if(flag){
			//读取数据到buffer2,输出buffer的数据到文件	
				buffer2.clear();
				n=input.read(buffer2);
				
				if(n<0){    				
					buffer.limit(buffer.limit()-boundaryLength*2-65);
					out.write(buffer);
					break;
				}
				buffer2.flip();	
				
				m+=buffer.limit();
				checkSize(m);			
				out.write(buffer);
				flag=false;
				
			}else{
				buffer.clear();
				n=input.read(buffer);
				if(n<0){    				
					buffer2.limit(buffer2.limit()-boundaryLength*2-65);
					out.write(buffer2);
					break;
				}
				buffer.flip();
				
				m+=buffer2.limit();
				checkSize(m);
				out.write(buffer2);
				flag=true;
				
			}
		}
		out.close();
		input.close();
		return true;
	}





	/**
     * 读取到文件大小了，这下就好办了。
     * */
	private boolean output(FileChannel out, long size) throws IOException {
		if(size<=0){//如果文件大小是0,那就只好用原来的那个了
			output(out);
		}
		long hasReaded=buffer.limit()-buffer.position();
		//System.out.println("hasReaded:"+hasReaded);
		out.write(buffer);
		int n;

		while(true){	
				buffer.clear();
				n=input.read(buffer);
				//System.out.println("n:"+n);
				if(n<0){  
					return false;					
				}
				
				buffer.flip();	
				hasReaded+=n;
				
				if(hasReaded>=size){
					buffer.limit(buffer.limit()-(int)(hasReaded-size));
					out.write(buffer);
					out.close();
					input.close();
					return true;
				}	
	
				out.write(buffer);		
		}
		
	}




	private boolean checkSize(int size) {
		return control.checkSize(size);
	}



	private boolean checkType(String Type) {
		return control.checkType(Type);
	}


	private File createFile(String path, String fileName) {		
		return control.CreateFile(path, fileName);
	}
	
	/**
	 * 默认的文件监控，大小：5MB,类型不定，位置：tomcat+fileName
	 * */
	class Control implements UploadControlable{

		public File CreateFile(String path, String fileName) {
			if(path==null){
				path="";
				}
			return new File(path,fileName);
		}

		public boolean checkSize(long size) {
			if(size>fileSize){
				return true;
			}
			return false;
		}

		public boolean checkType(String Type) {			
			return false;
		}}
}
